package taskinstance;

import java.util.ArrayList;

import datatransfer.DataTransferInstance;
import datatransfer.DataTransferInterface;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import osreencapsulation.OsreEncapsulation;
import osreencapsulation.OsreEncapsulationInterface;

import adapter.Adapter;
import adapter.AdapterInterface;

import taskmanager.TaskManager;

public class Task implements Runnable {

  protected String sourceIp;
  protected String targetIp;
  protected String urlSource;

  protected boolean osreCapsulation;
  protected boolean encryption;

  boolean isPending = true;
  protected String fetchedFileName = "";

  protected AdapterInterface adapter;
  protected OsreEncapsulationInterface osreEnc;
  protected DataTransferInterface dtf;

  protected TaskManager tm;

  public Task() {};

  public Task(String sourceIp, String targetIp, String urlSource, boolean osreCapsulation,
      boolean encryption) {
    // PropertyConfigurator.configure("log4j.properties");
    this.sourceIp = sourceIp;
    this.targetIp = targetIp;
    this.urlSource = urlSource;
    this.osreCapsulation = osreCapsulation;
    this.encryption = encryption;

    this.fetchedFileName = "";

    this.adapter = new Adapter(urlSource);
    this.osreEnc = new OsreEncapsulation(fetchedFileName);
  }

  public void setObserver(TaskManager tm) {
    this.tm = tm;
  }

  public void fetchDataAndEncapsulate() {
    class StartHelper implements Runnable {
      AdapterInterface adapter;
      OsreEncapsulationInterface osreEnc;
      String fetchedFileName;

      public StartHelper(AdapterInterface adapter, OsreEncapsulationInterface osreEnc,
          String fetchFileString) {
        this.adapter = adapter;
        this.osreEnc = osreEnc;
        this.fetchedFileName = fetchFileString;
      }

      @Override
      public void run() {
        // TODO Auto-generated method stub
        adapter.fetchData(fetchedFileName, false, false);
        while (!adapter.isComplete()) {
          try {
            Thread.sleep(5000);
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
        osreEnc.doEncapsulation(fetchedFileName + ".osre");
      }
    }

    new Thread(new StartHelper(adapter, osreEnc, fetchedFileName)).start();
  }

  public void run() {
    this.dtf = new DataTransferInstance(fetchedFileName, targetIp);

    ArrayList<Task> completeArrayList = tm.getCompleteList();
    ArrayList<Task> failedArrayList = tm.getFailedList();
    ArrayList<Task> runningArrayList = tm.getRunningList();

    while (!osreEnc.isComplete()) {
      try {
        Thread.sleep(2000);
      } catch (Exception e) {
        // TODO: handle exception
      }
    }

    tm.lockTargetIp(targetIp);
    isPending = false;

    dtf.start();
    while (!dtf.isComplete()) {
      try {
        Thread.sleep(1000);
        if (dtf.isError()) {
          tm.releaseTargetIp(targetIp);
          synchronized (runningArrayList) {
            runningArrayList.remove(this);
            failedArrayList.add(this);
            return;
          }
        }
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
    tm.releaseTargetIp(targetIp);
    synchronized (runningArrayList) {
      runningArrayList.remove(this);
      completeArrayList.add(this);
    }
  }

  public Boolean isPending() {
    return isPending;
  }

  public String getTargetIp() {
    return targetIp;
  }

  public String geturlSource() {
    return urlSource;
  }

  public String getProgress() {
    if (!adapter.isComplete()) {
      return adapter.getProgress();
    } else if (!osreEnc.isComplete()) {
      return osreEnc.getProgress();
    }
    return dtf.getState();
  }

  public void suspend() {
    dtf.suspend();
    // TODO release clock.
    // tm.releaseTargetIp(targetIp);
  }

  public void resume() {
    dtf.resume();
    // TODO acquire clock.
    // tm.lockTargetIp(targetIp);
  }
}
